package database

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/astaxie/beego/logs"
	"github.com/garyburd/redigo/redis"
	"time"
	"wonlicsys/api/v1"
)

var pool *redis.Pool

func GetRedis() *redis.Pool {
	pool = &redis.Pool{
		MaxIdle: 16, //最初的连接数量
		// MaxActive:1000000,    //最大连接数量
		MaxActive:   0,   //连接池最大连接数量,不确定可以用0（0表示自动定义），按需分配
		IdleTimeout: 300, //连接关闭时间 300秒 （300秒不使用自动关闭）
		Dial: func() (redis.Conn, error) { //要连接的redis数据库
			c, err := redis.Dial("tcp", v1.Conf.RedHost+":"+v1.Conf.RedPort)
			if err != nil {
				return nil, err
			}
			if v1.Conf.RedAuth != "" {
				if _, err := c.Do("AUTH", v1.Conf.RedAuth); err != nil {
					logs.Error(err, "错误--------->")
					c.Close()
					return nil, err
				}
			}

			//分配数据库
			if _, err := c.Do("SELECT", v1.Conf.RedSelect); err != nil {
				logs.Error(err, "错误--------->")
				c.Close()
				return nil, err
			}

			return c, nil
		},
		//ping
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			_, err := c.Do("PING")
			if err != nil {
				logs.Error(err)
				return fmt.Errorf("ping redisPkg error: %s", err)
			}
			return nil
		},
	}
	return pool
}

func InitRedis() error {
	pool = GetRedis()
	return nil
}

/**
redis  SET
*/
func RdbSet(key, v string) error {
	var con = pool.Get()
	defer con.Close()
	_, err := con.Do("SET", key, v)
	if err != nil {
		logs.Error("set error", err.Error())
		return err
	}
	return nil
}

/**
redis  GET
*/
func RdbGet(key string) (string, error) {
	var con = pool.Get()
	defer con.Close()
	val, err := redis.String(con.Do("GET", key))
	if err != nil {
		logs.Error("get error", err.Error())
		return "", err
	}
	return val, nil
}

/**
redis EXPIRE
*/
func RdbSetKeyExp(key string, ex int) error {
	var con = pool.Get()
	defer con.Close()
	_, err := con.Do("EXPIRE", key, ex)
	if err != nil {
		logs.Error("set error", err.Error())
		return err
	}
	return nil
}

func RdbSetExp(key, v string, ex int) error {
	var con = pool.Get()
	defer con.Close()
	_, err := con.Do("SET", key, v, "EX", ex)
	if err != nil {
		logs.Error("set error", err.Error())
		return err
	}
	return nil
}

func RdbSetRange(key, v string) error {
	var con = pool.Get()
	defer con.Close()
	_, err := con.Do("SETRANGE", key, v, "0")
	if err != nil {
		logs.Error("set error", err.Error())
		return err
	}
	return nil
}

/**
redis EXISTS
*/
func RdbCheck(key string) bool {
	var con = pool.Get()
	defer con.Close()
	b, err := redis.Bool(con.Do("EXISTS", key))
	if err != nil {
		return false
	}
	return b
}

/**
redis DEL
*/
func RdbDel(key string) error {
	var con = pool.Get()
	defer con.Close()
	_, err := con.Do("DEL", key)
	if err != nil {
		fmt.Println(err)
		return err
	}
	return nil
}

/**
redis SETNX
*/
func RdbSetJson(key string, data interface{}) error {
	var con = pool.Get()
	defer con.Close()
	value, _ := json.Marshal(data)
	n, _ := con.Do("SETNX", key, value)
	if n != int64(1) {
		return errors.New("set failed")
	}
	return nil
}

/**
redis GET
return map
*/
func RdbGetJson(key string) (map[string]string, error) {
	var con = pool.Get()
	defer con.Close()
	var jsonData map[string]string
	bv, err := redis.Bytes(con.Do("GET", key))
	if err != nil {
		logs.Error("get json error", err.Error())
		return nil, err
	}
	errJson := json.Unmarshal(bv, &jsonData)
	if errJson != nil {
		logs.Error("json nil", err.Error())
		return nil, err
	}
	return jsonData, nil
}

/**
redis hSet 注意 设置什么类型 取的时候需要获取对应类型
*/
func RdbHSet(key string, field string, data interface{}) error {
	var con = pool.Get()
	defer con.Close()
	_, err := con.Do("HSET", key, field, data)
	if err != nil {
		logs.Error("hSet error", err.Error())
		return err
	}
	return nil
}

/**
redis hmSet 注意 设置什么类型 取的时候需要获取对应类型
*/
func RdbHMSet(key string, value interface{}, validity int) error {
	var con = pool.Get()
	defer con.Close()
	_, err := con.Do("hmset", redis.Args{}.Add(key).AddFlat(value)...)
	if err != nil {
		return err
	}
	err = RdbSetKeyExp(key, validity)
	if err != nil {
		return err
	}
	return nil
}

/**
redis hGet 注意 设置什么类型 取的时候需要获取对应类型
*/
func RdbHGet(key string) (interface{}, error) {
	var con = pool.Get()
	defer con.Close()
	data, err := con.Do("HGETALL", key)
	if err != nil {
		logs.Error("hGet error", err.Error())
		return nil, err
	}
	return data, nil
}

/**
redis hGetAll
return map
*/
func RdbHGetAll(key string) (map[string]string, error) {
	var con = pool.Get()
	defer con.Close()
	data, err2 := redis.StringMap(con.Do("HGETALL", key))
	_, err := data, err2
	if err != nil {
		logs.Error("hGetAll error", err.Error())
		return nil, err
	}
	return data, nil
}

/**
redis INCR 将 key 中储存的数字值增一
*/
func RdbIncr(key string) error {
	var con = pool.Get()
	defer con.Close()
	_, err := con.Do("INCR", key)
	if err != nil {
		logs.Error("INCR error", err.Error())
		return err
	}
	return nil

}

/**
redis INCRBY 将 key 所储存的值加上增量 n
*/
func RdbIncrBy(key string, n int) error {
	var con = pool.Get()
	defer con.Close()
	_, err := con.Do("INCRBY", key, n)
	if err != nil {
		logs.Error("INCRBY error", err.Error())
		return err
	}
	return nil
}

/**
redis DECR 将 key 中储存的数字值减一。
*/
func RdbDecr(key string) error {
	var con = pool.Get()
	defer con.Close()
	_, err := con.Do("DECR", key)
	if err != nil {
		logs.Error("DECR error", err.Error())
		return err
	}
	return nil
}

/**
redis DECRBY 将 key 所储存的值减去减量 n
*/
func RdbDecrBy(key string, n int) error {
	var con = pool.Get()
	defer con.Close()
	_, err := con.Do("DECRBY", key, n)
	if err != nil {
		logs.Error("DECRBY error", err.Error())
		return err
	}
	return nil
}

/**
redis SADD 将一个或多个 member 元素加入到集合 key 当中，已经存在于集合的 member 元素将被忽略。
*/
func RdbSAdd(key, v string) error {
	var con = pool.Get()
	defer con.Close()
	_, err := con.Do("SADD", key, v)
	if err != nil {
		logs.Error("SADD error", err.Error())
		return err
	}
	return nil
}

/**
redis SMEMBERS 返回集合 key 中的所有成员。
return map
*/
func RdbSMembers(key string) (interface{}, error) {
	var con = pool.Get()
	defer con.Close()
	data, err := redis.Strings(con.Do("SMEMBERS", key))
	if err != nil {
		logs.Error("json nil", err)
		return nil, err
	}
	return data, nil
}

/**
redis SISMEMBER 判断 member 元素是否集合 key 的成员。
return bool
*/
func RdbSISDelMembers(key, v string) error {
	var con = pool.Get()
	defer con.Close()
	_, err := redis.Bool(con.Do("SREM", key, v))
	if err != nil {
		logs.Error("SISMEMBER error", err.Error())
		return err
	}
	return nil
}

/**
redis SISMEMBER 判断 member 元素是否集合 key 的成员。
return bool
*/
func RdbSISMembers(key, v string) bool {
	var con = pool.Get()
	defer con.Close()
	b, err := redis.Bool(con.Do("SISMEMBER", key, v))
	if err != nil {
		logs.Error("SISMEMBER error", err.Error())
		return false
	}
	return b
}
